/*---------------------------------------头文件---------------------------------------*/
#include <stdio.h>  // “标准输入输出库” ---> 提供printf、perror等输入输出函数声明
#include <stdlib.h> // “标准库” ----------> 提供exit、EXIT_FAILURE等进程控制和通用函数声明
//#include <errno.h>  // “错误处理库” ------> 定义了全局错误码变量errno，用于标识系统调用的错误类型
#include <unistd.h> // “POSIX系统调用库” -> 提供read、write、close、unlink等系统调用函数声明

/* 说明使用下面的函数的时候需要包含下面的头文件：
*       1. mkfifo
*/
#include <sys/types.h>
#include <sys/stat.h>

/* 说明使用下面的函数的时候需要包含下面的头文件：
*       1. open
*/
//#include <sys/types.h>
//#include <sys/stat.h>
#include <fcntl.h>

/*---------------------------------------宏定义---------------------------------------*/
// 错误处理宏：打印错误信息并退出程序
#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


/*---------------------------------------主程序---------------------------------------*/
int main(int argc, char *argv[])
{
    /*----------------------------第一步：创建命名管道文件----------------------------*/
    //1.创建命名管道文件"tp"，权限为0644（所有者读写，其他用户读）
    mkfifo("tp", 0644);

    /*----------------------------第二步：打开源文件和管道文件----------------------------*/
    //2.打开源文件"abc"（只读模式）
    int infd;
    infd = open("abc", O_RDONLY);
    if (infd == -1)
        ERR_EXIT("open"); // 打开失败则报错退出

    //3.打开命名管道"tp"（只写模式）
    int outfd;
    outfd = open("tp", O_WRONLY);
    if (outfd == -1)
        ERR_EXIT("open"); // 打开失败则报错退出

    /*----------------------------第三步：循环读取源文件内容并将其写到命名管道中----------------------------*/
    //4.定义缓冲区用于存储读取的文件内容
    char buf[1024]; 
    //5.记录每次读取的字节数
    int n;          

    //6.循环读取源文件内容，直到读取到0字节 <--- 文件结束
    while ((n = read(infd, buf, 1024)) > 0)
    {
        //6.1：将读取的内容写入命名管道
        write(outfd, buf, n);
    }

    //7.关闭源文件和命名管道的文件描述符
    close(infd);
    close(outfd);

    return 0;
}